﻿//----------------------------------------------------------------
// Desc: 
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2009-10-13
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


#include "FUI_Define.h"


//----------------------------------------------------------------
//
//----------------------------------------------------------------
enum EF_UI_BUTTON_STATE
{
    eUBS_Normal,        // 普通
    eUBS_Suspend,       // 悬停
    eUBS_Press,         // 按下
    eUBS_Disable,      // 灰掉

    eUBS_Max,
};


#pragma pack(push, 1)


//----------------------------------------------------------------
// 位置信息
//----------------------------------------------------------------
class FAPI fuPoint
{
    FUI_DECLARE_STRUCT(fuPoint)

public:
    fuPoint(){ clear(); }
    fuPoint(funit x, funit y){ nX = x; nY = y; }
#ifdef WIN32
    fuPoint(const POINT* point){ nX = (funit)point->x; nY = (funit)point->y; }
#endif

    FINLINE void add(funit x, funit y){ nX += x; nY += y; }
    FINLINE void set(funit x, funit y){ nX = x;  nY = y;  }
    FINLINE void clear()              { nX = 0;  nY = 0;  }
#ifdef WIN32
    FINLINE fuPoint& operator = (const POINT& point);
#endif
    FINLINE bool operator == (const fuPoint& r) const { return nX == r.nX && nY == r.nY; }

    funit nX; // X 坐标
    funit nY; // Y 坐标
};


//----------------------------------------------------------------
// 尺寸信息
//----------------------------------------------------------------
class FAPI fuSize
{
    FUI_DECLARE_STRUCT(fuSize)

public:
    fuSize(){ clear(); }
    fuSize(funit w, funit h){ nW = w; nH = h; }

    FINLINE void add(funit w, funit h){ nW += w; nH += h; }
    FINLINE void set(funit w, funit h){ nW = w;  nH = h;  }
    FINLINE void clear()              { nW = 0;  nH = 0;  }
    FINLINE bool operator == (const fuSize& r) const { return nW == r.nW && nH == r.nH; }

    funit nW; // 宽度
    funit nH; // 高度
};


//----------------------------------------------------------------
// 矩形区域信息
//   注意：这里使用RECT时都是视left,right,top,bottom为有效位置，而WINDOWS的CRect视这些无效
//----------------------------------------------------------------
class FAPI fuRect
{
    FUI_DECLARE_STRUCT(fuRect)

public:
    // 构造
    fuRect(){}
    fuRect(funit x, funit y, funit w, funit h){ set(x, y, w, h); }
#ifdef WIN32
    fuRect(const RECT* rect){ set(rect); }
#endif
    // 操作符
#ifdef WIN32
    FINLINE fuRect& operator =  (const RECT& _rect);
#endif
    FINLINE fuRect& operator *= (const float _right);
    FINLINE fuRect& operator /= (const float _right);
    FINLINE fuRect  operator +  (const fuRect& _right);
    FINLINE fuRect& operator += (const fuRect& _right);

    FINLINE bool operator == (const fuRect& r) const { return uPos == r.uPos && uSize == r.uSize; }

    // 取设操作
#ifdef WIN32
    FINLINE void set(const RECT* rect);
#endif
    FINLINE void set(funit x, funit y, funit w, funit h);
    FINLINE void get(funit& x, funit& y, funit& w, funit& h);
    // GDI+的获得函数
#ifdef WIN32
    FINLINE void get_gdiplus(RECT* rect);
    // D3D用的获取函数
    FINLINE void get_d3d(RECT* rect, int frame);
    // D3D用的获取函数，并自动修正在区间内
    FINLINE void get_d3d(RECT* rect, int frame, fuRect* interzone);
#endif
    // 通过区间裁减自己
    FINLINE void cut(fuRect* interzone);
    // 通过区间修正自己
    FINLINE void amend(fuRect* interzone);
    // 通过区间合并自己成为新的区域
    FINLINE void unite(fuRect* interzone);
    // 通过父区域及参数填充自己，不修正自己
    FINLINE bool fillbyfather(const fuRect* father, BYTE align, funit sw, funit sh);
    // 清空自己
    FINLINE void clear(){ uPos.clear(); uSize.clear(); }
    // 测试自己是不是有效的，或者是空的
    FINLINE bool is_empty() const { return (uSize.nW <= 0 && uSize.nH <= 0); }
    // 测试某点是否在内部
    FINLINE bool ptin(funit x, funit y);
    // 测试区域是否在内部
    FINLINE bool rectin(fuRect* rc);
    // 测试两个区是否存在交叉
    FINLINE bool cross(fuRect* rc);
    // 生成九宫目标(nineRect[9])
    FINLINE void make_dst_ninepal(fuRect* dstRect, fuRect* srcRect, fuRect* center, fuRect* nineRect);
    // 生成九宫图片源区域(nineRect[9])
    FINLINE void make_src_ninepal(fuRect* srcRect, fuRect* center, fuRect* nineRect);
    // 生成目标三宫(threeRect[3])
    FINLINE void make_dst_threepal(fuRect* dstRect, fuRect* srcRect, fuRect* center, fuRect* threeRect, bool horizontal);
    // 生成源三宫(threeRect[3])
    FINLINE void make_src_threepal(fuRect* srcRect, fuRect* center, fuRect* threeRect, bool horizontal);
    // 通过目标区域设置自己，并带缩放
    FINLINE void scale(fuRect* src, float scale);
    // 得到GDI的右下
    FINLINE funit Right() const  { return uPos.nX + uSize.nW; }
    FINLINE funit Bottom() const { return uPos.nY + uSize.nH; }
    FINLINE void inflate(funit v){ inflate(v, v); }
    FINLINE void inflate(funit x, funit y){ uPos.nX -= x, uPos.nY -=y, uSize.nW += x*2.0f, uSize.nH += y*2.0f; }
    FINLINE void offset(funit x, funit y){ uPos.nX += x, uPos.nY += y; }
    FINLINE void move_to(funit x, funit y){ uPos.nX = x, uPos.nY = y; }
	// 直接转为RECT数据
#ifdef WIN32
	FINLINE RECT rect(){ RECT r = { (long)uPos.nX, (long)uPos.nY, (long)uSize.nW, (long)uSize.nH}; return r; }
#endif
    // 横向拆分区域
    FINLINE void split_w(fuRect* dst_left, fuRect* dst_right, funit left_w);
    // 纵各拆分区域
    FINLINE void split_h(fuRect* dst_up, fuRect* dst_down, funit up_h);

    fuPoint uPos;   // 位置
    fuSize uSize;   // 尺寸

protected:
    FINLINE void fill_ninepal(fuRect* nineRect, funit& w1, funit& w2, funit& w3, funit& h1, funit& h2, funit& h3, funit dstx, funit dsty);
};

//----------------------------------------------------------------
// UI系统的上下左右与RECT的left...转换
//----------------------------------------------------------------
struct FAPI FUI_RECT
{
    LONG T;     // RECT->left
    LONG B;     // RECT->top
    LONG L;     // RECT->right
    LONG R;     // RECT->bottom
};

//----------------------------------------------------------------
// 资源对象中的单个图片
//----------------------------------------------------------------
#define FUI_ResPic_Auto_Mask_Function(name)\
    bool Is##name()         { return has(name, pic_mask);           }\
    void Set##name(bool vl) { return mask_set(name, vl, pic_mask);  }

struct FAPI fuResPic
{
    FUI_DECLARE_STRUCT(fuResPic)

    funit sx, sy, sw, sh;       // 在资源文件中的坐标
    BYTE name_offset;           // 文件名在源始路径中的偏移（注意动态检查）
    ACHAR src_path[MAX_PATH];   // 源始路径
    BYTE draw_mode;             // 图片的绘制模式
    BYTE sample_mode;           // 采样模式
    fuRect nine_center;         // 九宫的中心
    FIDHASH pic_hash;           // 图片HASH（注意动态检查）
    funit lodx, lody;           // 如果是从合并合加载的时候合并图位置（编辑器使用）
    BYTE use_srcpath;           // 使用的是源始路径加载图片（编辑器使用）
    WORD pic_mask;              // 功能标志
    BYTE reserve[30];           // 保留备用

    enum enumResPicMask
    {
        NoShowInEditView        = 1<<0, // 不在编辑视图可见
        NoShowInPreView         = 1<<1, // 不在预置视图可见
    };
    FUI_ResPic_Auto_Mask_Function(NoShowInEditView);
    FUI_ResPic_Auto_Mask_Function(NoShowInPreView);

    fuResPic()
    {
        memset(this, 0, sizeof(*this));
    }
    const ACHAR* name()
    {
        return src_path + name_offset;
    }
    void name_examine()
    {
        name_offset = (BYTE)(FUI_FileNamePositionA(src_path) - src_path);
        pic_hash = FUI_GetHashA(name());
    }
    void mask_set(WORD test_mask, bool add, WORD& data_mask)
    {
        if (add) data_mask |= test_mask;
        else     data_mask &= ~test_mask;
    }
    bool has(WORD test_mask, WORD& data_mask)
    {
        return (data_mask & test_mask) != 0;
    }
};
typedef FUI_Vector< fuResPic >          FV_UI_RES_PIC;


//----------------------------------------------------------------
// 资源对象
//----------------------------------------------------------------
struct FAPI fuResFile
{
    FUI_DECLARE_STRUCT(fuResFile)

    struct BASE
    {
        ACHAR res_name[FUEL_UI_RES_NAME];// 资源文件名
        WORD width, height;             // 资源尺寸
        FIDHASH res_hash;               // 名字HASH
        BYTE reserve[32];               // 保留备用

        BASE()
        {
            memset(this, 0, sizeof(*this));
        }
    };

    BASE nBase;
    FV_UI_RES_PIC vecPicture;           // 图片列表

    void examine()
    {
        nBase.res_hash = FUI_GetHashA(nBase.res_name);
        for (size_t i = 0; i < vecPicture.size(); ++i)
        {
            vecPicture[i].name_examine();
        }
    }
    const ACHAR* file(const ACHAR* res_path)
    {
        static FUI_StringA str;
        if (str.empty())
            str.reserve(MAX_PATH);
        str.clear();
        str = res_path;
        str += nBase.res_name;
        str += _FTA(".png");
        return str.c_str();
    }
};
typedef FUI_Vector< fuResFile >         FV_UI_RES_FILE;


//----------------------------------------------------------------
// 图片数据
//----------------------------------------------------------------
struct FAPI fuPicture
{
    FUI_DECLARE_STRUCT(fuPicture)

    FIDHASH pic_hash;       // 我的图片HASH
    FIDHASH res_hash;       // 我的资源HASH
    DWORD ref_time;         // 上次刷新图片索引时间
    fuResFile* pfile;       // 资源关联地址（要注意刷新与绑定）
    fuResPic* ppic;         // 图片关联地址（要注意刷新与绑定）

    fuPicture()
		:pic_hash(0)
		,res_hash(0)
		,ref_time(0)
		,pfile(0)
		,ppic(0)
    {}
    FINLINE bool IsValid() const
    {
        return pic_hash && res_hash;
    }
    FINLINE void Init(FIDHASH pic, FIDHASH res, bool clear_all = false)
    {
        if (clear_all)
            Clear();
        pic_hash = pic, res_hash = res;
    }
    FINLINE void Clear()
    {
        ref_time = 0;
        pfile = 0;
        ppic = 0;
        pic_hash = 0, res_hash = 0;
    }
};


//----------------------------------------------------------------
// 字体参数数据
//----------------------------------------------------------------
struct FAPI fuFontProp
{
    FUI_DECLARE_STRUCT(fuFontProp)

    WORD nGroupIndex;       // 文字组索引 (0-250之间)
    BYTE nEffectType;       // 文字的绘制效果（EF_UI_TEXT_EFFECT_TYPE）

    fuFontProp()
		:nGroupIndex(0)
		,nEffectType(eUTET_Normal)
    {}
};


//----------------------------------------------------------------
// 字体组数据
//----------------------------------------------------------------
struct FAPI fuFontGroup
{
    FUI_DECLARE_STRUCT(fuFontGroup)

    ACHAR szTDesc[FUEL_UI_OBJ_NAME];   // 字体说明
    ACHAR szFontName[FUEL_UI_FNT_NAME];// 字体名
    BYTE  nFontSize;        // 字体大小
    DWORD dwFontColor;      // 字体颜色
    BYTE  bFontSmooth;      // 是否使用边缘平滑
    BYTE  bBold;            // 是否是粗体
    DWORD dwEffectColor;    // 效果颜色
    DWORD nFontIndex;       // 由应用程序使用的字体ID
    BYTE  reserve[16];

    fuFontGroup()
		:nFontSize(14)
		,bFontSmooth(0)
		,bBold(0)
		,dwFontColor(0xFFFFFFFF)
		,dwEffectColor(0xFF323232)
		,nFontIndex(0)
    {
        memset(szTDesc, 0, sizeof(szTDesc));
        memset(szFontName, 0, sizeof(szFontName));
        memset(reserve, 0, sizeof(reserve));
        strcpy(szTDesc, _FTA("默认字体"));
        strcpy(szFontName, _FTA("font/dsf.ttf"));
    }
    void load_examine()
    {
        if (!*szFontName)
            nFontSize = 0;
        else if (nFontSize < 10)
            nFontSize = 10;
        else if (nFontSize > 64)
            nFontSize = 64;
    }
};


//----------------------------------------------------------------
// 菜单组
//----------------------------------------------------------------
struct FAPI fuMenuGroup
{
    FUI_DECLARE_STRUCT(fuMenuGroup)

    ACHAR szMDesc[FUEL_UI_OBJ_NAME];// 菜单说明
    fuPicture uBack;                // 菜单背景图
    fuPicture uHasChildN;           // 有子项时普通项
    fuPicture uSuspend;             // 菜单项悬停状态图
    DWORD nLineHeight;              // 行高
    DWORD nMinLineWidth;            // 最小行宽
    BYTE fntAlgin;                  // 字体对齐模式
    fuFontProp uFntNormal;			// 普通状态字体
    fuFontProp uFntSuspend;			// 悬停状态字体
    fuFontGroup* pfntNormal;        // 由应用使用的普通状态字体信息
    fuFontGroup* pfntSuspend;       // 由应用使用的悬停状态字体信息
    fuPicture uHasChildS;           // 有子项时悬停项
    SHORT fntIndentX;               // 文字横向缩进
    BYTE frameUp;                   // 上下左右的四个边框
    BYTE frameDown;
    BYTE frameLeft;
    BYTE frameRight;
    BYTE reserve[22];

    fuMenuGroup()
		:nLineHeight(16)
		,nMinLineWidth(120)
		,fntAlgin(eUAM_LeftMiddle)
		,pfntNormal(0)
		,pfntSuspend(0)
        ,fntIndentX(0)
        ,frameUp(0)
        ,frameDown(0)
        ,frameLeft(0)
        ,frameRight(0)
    {
        memset(szMDesc, 0, sizeof(szMDesc));
        memset(reserve, 0, sizeof(reserve));
    }
};

//----------------------------------------------------------------
// 按钮组
//----------------------------------------------------------------
struct FAPI fuButtonGroup
{
    FUI_DECLARE_STRUCT(fuButtonGroup)

    ACHAR szBDesc[FUEL_UI_OBJ_NAME];              // 按钮说明
    fuPicture uBtnPic[eUBS_Max];    // 图片
    fuFontProp uBtnFnt[eUBS_Max];	// 字体
    WORD reserve;

    fuButtonGroup()
    {
        memset(szBDesc, 0, sizeof(szBDesc));
    }
};


//----------------------------------------------------------------
// 滚动条组
//----------------------------------------------------------------
struct FAPI fuScrollBarGroup
{
    FUI_DECLARE_STRUCT(fuScrollBarGroup)

    ACHAR szSDesc[FUEL_UI_OBJ_NAME];      // 滚动条说明
    fuPicture uBack;        // 背景图片
    WORD nBtn[3];           // 按钮组的编号

    fuScrollBarGroup()
    {
        memset(szSDesc, 0, sizeof(szSDesc));
		memset(nBtn, 0, sizeof(nBtn));
	}
};


#pragma pack(pop)


typedef FUI_Vector< fuFontGroup >       FV_UI_FONT_GROUP;
typedef FUI_Vector< fuMenuGroup >       FV_UI_MENU_GROUP;
typedef FUI_Vector< fuButtonGroup >     FV_UI_BUTTON_GROUP;
typedef FUI_Vector< fuScrollBarGroup >  FV_UI_SCROLL_GROUP;


//----------------------------------------------------------------
// 联接内联函数实现文件
//----------------------------------------------------------------
#include "FUI_Base_inl.h"
